package com.millstein.tsinglog.controller;

import com.millstein.tsinglog.annotation.ResponseResult;
import com.millstein.tsinglog.annotation.ShiroAccessLog;
import com.millstein.tsinglog.commons.constant.SystemConstant;
import com.millstein.tsinglog.model.dto.user.ChangePasswordDTO;
import com.millstein.tsinglog.model.dto.user.UserAssignRoleDTO;
import com.millstein.tsinglog.model.dto.user.UserLoginDTO;
import com.millstein.tsinglog.model.dto.user.UserSaveDTO;
import com.millstein.tsinglog.model.vo.result.PageResult;
import com.millstein.tsinglog.result.ProfileResult;
import com.millstein.tsinglog.model.vo.sys.UserVo;
import com.millstein.tsinglog.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;

@RestController
@RequestMapping("/user")
@ResponseResult
@CrossOrigin
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户登录的方法
     * @param userLoginDTO 登录时用户的信息
     * @return
     */
    @PostMapping("/login")
    @ShiroAccessLog("进行登录")
    public String login(@RequestBody @Valid UserLoginDTO userLoginDTO) {

        Subject subject = SecurityUtils.getSubject();

        String username = userLoginDTO.getUsername();
        String rawPassword = userLoginDTO.getPassword();

        // 1.获取加密盐
        String salt = userService.getUserByUsername(username).getSalt();
        // 2.将密码加密
        String password = new SimpleHash(SystemConstant.ENCRYPT_ARITHMETIC, rawPassword, salt, SystemConstant.ENCRYPT_TIMES).toString();

        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);

        subject.login(token);

        // 4.获取sessionId
        String sessionId = (String) subject.getSession().getId();

        // 5.返回数据
        return sessionId;
    }

    /**
     * 用户登录成功之后，获取用户信息
     *      1.获取用户id
     *      2.根据用户id查询用户
     *      3.构建返回值对象
     *      4.响应
     */
    @GetMapping("/profile")
    public ProfileResult profile(HttpServletRequest request) {

        // 以下是从Session中获取信息
        Subject subject = SecurityUtils.getSubject();
        // 获取所有的安全数据
        PrincipalCollection principals = subject.getPrincipals();
        // 获取安全数据
        ProfileResult result = (ProfileResult) principals.getPrimaryPrincipal();

        return result;
    }



    /**
     * 重置密码
     * @param userLoginDTO 用户信息
     * @return
     */
    @PostMapping("/resetPassword")
    @RequiresPermissions("user:changePassword")
    @ShiroAccessLog("重置用户密码")
    public void resetPassword(@Valid @RequestBody UserLoginDTO userLoginDTO) {
        userService.resetPassword(userLoginDTO);
    }

    /**
     * 为用户分配角色
     * @param userAssignRoleDTO
     * @return
     */
    @PostMapping("/assignRole")
    @RequiresPermissions("user:assignRole")
    @ShiroAccessLog("分配用户角色")
    public void assignRole(@Valid @RequestBody UserAssignRoleDTO userAssignRoleDTO) {
        userService.assignRole(userAssignRoleDTO);
    }

    /**
     * 新增用户
     * @param userSaveDTO
     * @return
     */
    @PostMapping("/insertUser")
    @RequiresPermissions("user:insert")
    @ShiroAccessLog("新增用户信息")
    public void insertUser(@Valid @RequestBody UserSaveDTO userSaveDTO) {
        userService.insertUser(userSaveDTO);
    }

    /**
     * 条件及分页查询用户信息
     * @param currentPage 当前页
     * @param pageSize 一页包含的数据
     * @param keyword 关键字
     * @return
     */
    @GetMapping("/getUserByPage")
    @RequiresPermissions("user:query")
    @ShiroAccessLog("查询用户信息")
    public PageResult<UserVo> getUserByPage(Integer currentPage,
                                            Integer pageSize,
                                            String keyword) {
        return userService.getUserByPage(currentPage, pageSize, keyword);
    }

    /**
     * 更新用户
     * @param userSaveDTO
     * @return
     */
    @PostMapping("/updateUser")
    @RequiresPermissions("user:update")
    @ShiroAccessLog("更新用户信息")
    public void updateUser(@Valid @RequestBody UserSaveDTO userSaveDTO) {
        userService.updateUser(userSaveDTO);
    }

    /**
     * 修改用户的启用状态
     * @param id 用户id
     * @param usable 1启用，0禁用
     * @return
     */
    @GetMapping("/changeUsable")
    @RequiresPermissions("user:update")
    @ShiroAccessLog("修改用户的启用状态")
    public void changeUsable(Long id, Short usable) {
        userService.changeUsable(id, usable);
    }

    /**
     * 根据ids批量删除用户信息
     * @param ids
     * @return
     */
    @GetMapping("/deleteByIds")
    @RequiresPermissions("user:delete")
    @ShiroAccessLog("删除用户信息")
    public void deleteByIds(@RequestParam("ids") List<Long> ids) {
        userService.deleteByIds(ids);
    }

    /**
     * 修改密码
     * @param changePasswordDTO
     * @return
     */
    @PostMapping("/changePassword")
    @ShiroAccessLog("修改用户密码")
    public void changePassword(@Valid @RequestBody ChangePasswordDTO changePasswordDTO) {
        userService.changePassword(changePasswordDTO);
    }
}
